/**
 * @file Define the LeadBarService class in this module
 * 
 * @author Steve Gao<gaofu@parllay.com>
 */
const winston = require('winston');
const mongoose = require('mongoose');
const moment = require('moment');
const async = require('async');

const BaseService = require('./base-service').BaseService;
const { Configuration } = require('../constants');
const utils = require('../utils');
const models = require('../models/mongodb');


const defaultLeadflowMetadata = {
    "name": "My new LeadBar",
    "type": "top-down",
    "title": "弹框标题",
    "body": "",
    "buttonText": "按钮文字",
    "backgroundColor": "#ebebeb",
    "buttonColor": "#4A90E2",
    "titleColor": "#333",
    "fontColor": "#666",
    "buttonFontColor": "#ffffff",
    "fields": [
        {
            "name": "邮箱",
            "val": "email",
            "isRequired": true
        }
    ],
    "thank": "设置感谢信息",
    "connectParllayCRM": false,
    "trackingId": ''
};
const defaultSettings = {
    emails: [],
    user: {}
};
/**
 * The main service class for leadbar
 * 
 * @class LeadBarService
 */
class LeadBarService extends BaseService {

    constructor(context) {
        super(context);
        this.initializeMongoContext();
        this.initializeModels();
    }

    /**
     * Initialize MongoDB Context
     * 
     * @name initializeMongoContext
     */
    initializeMongoContext() {
        var mongooseConfig = this.getApplicationConfiguration(Configuration.MONGOOSE);

        if (mongooseConfig) {
            if (!mongooseConfig.options) {
                mongooseConfig.options = {
                    db: {
                        native_parser: true
                    },
                    server: {
                        poolSize: 100
                    }
                };
            }
            var connString = mongooseConfig.connection_string;
            if (mongooseConfig.user && mongooseConfig.pass) {
                options.user = mongooseConfig.user;
                options.pass = mongooseConfig.pass;
            }
            this.mongoose.connect(connString, mongooseConfig.options);
        }
    }

    /**
     * Initialize the mongoose models
     * 
     * @name initializeModels
     */
    initializeModels() {
        this._User = this.mongoose.model('user', models.User);
        this._LeadFlow = this.mongoose.model('leadflow', models.LeadFlow);
        this._CollectedLead = this.mongoose.model('collected_lead', models.CollectedLead);
        this._SystemSetting = this.mongoose.model('system_setting', models.SystemSetting);
        this._FHTLiteResearch = this.mongoose.model('FHTLiteResearch', models.FHTLiteResearch);
    }

    get User() {
        return this._User;
    }

    get FHTLiteResearch() {
        return this._FHTLiteResearch;
    }

    get LeadFlow() {
        return this._LeadFlow;
    }

    get CollectedLead() {
        return this._CollectedLead;
    }

    get SystemSetting() {
        return this._SystemSetting;
    }

    get mongoose() {
        return mongoose;
    }


    /***
     * save FHT lite version research data
     * @name saveFHTLiteResearchData
     * @param {Object} singleData - All required data
     * @param {Function} parentCallback - The callback function
     * 
     * @returns {void}
     */
    saveFHTLiteResearchData(singleData, parentCallback) {
        var me = this;
        var loss_rate = Math.round((singleData.increased_Fans * 6) / ((singleData.total_Fans + singleData.increased_Fans * 3) * 4) * 100);
        var newResearchData = new me.FHTLiteResearch({
            user_agent: singleData.user_agent,
            remote_ip: singleData.remote_ip,
            session_id: singleData.session_id,
            http_referer: singleData.http_referer,
            send_frequency: singleData.send_frequency,
            send_date: singleData.send_date,
            send_time_interval: singleData.send_time_interval,
            increased_Fans: singleData.increased_Fans,
            total_Fans: singleData.total_Fans,
            loss_rate: loss_rate
        });
        newResearchData.save(function (error, result) {
            if (error) {
                me.logger.error('Error happened when save research data: ', error.message);
            }
            parentCallback(error, result);
        });
    }


    /***
    * get FHT Lite version research data statistics
    * @name getFHTLiteResearchStatistics
    * @param {Function} parentCallback - The callback function
    * 
    * @returns {void}
    */
    getFHTLiteResearchStatistics(StatisticsResult, parentCallback) {
        var me = this;
        //思路: 获取每一条记录的总数 / 全部记录的总数算  = 当前记录所占百分比
        async.parallel({
            send_frequency: (main_callback) => {
                async.parallel({
                    one: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_frequency: 1 }, callback)
                    },
                    two: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_frequency: 2 }, callback)
                    },
                    three: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_frequency: 3 }, callback)
                    },
                    four: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_frequency: 4 }, callback)
                    },

                }, (error, result) => {
                    if (error) {
                        me.logger.error(error);
                    }
                    var frequencyTotal = result.one.length + result.two.length + result.three.length + result.four.length;
                    StatisticsResult.send_frequency = {
                        'once': {
                            count: result.one.length,
                            percentage: `${Math.round(result.one.length / frequencyTotal * 100)}%`
                        },
                        'twice': {
                            count: result.two.length,
                            percentage: `${Math.round(result.two.length / frequencyTotal * 100)}%`
                        },
                        'thrice': {
                            count: result.three.length,
                            percentage: `${Math.round(result.three.length / frequencyTotal * 100)}%`
                        },
                        'quartic': {
                            count: result.four.length,
                            percentage: `${Math.round(result.four.length / frequencyTotal * 100)}%`
                        },
                        total: frequencyTotal

                    }
                    main_callback(error, 'done');
                })
            },
            send_date: (main_callback) => {
                async.parallel({
                    Monday: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_date: '周一' }, callback)
                    },
                    Tuesday: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_date: '周二' }, callback)
                    },
                    Wednesday: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_date: '周三' }, callback)
                    },
                    Thursday: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_date: '周四' }, callback)
                    },
                    Friday: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_date: '周五' }, callback)
                    }

                }, (error, result) => {
                    if (error) {
                        me.logger.error(error);
                    }
                    var dateTotal = result.Monday.length + result.Tuesday.length + result.Wednesday.length + result.Thursday.length
                        + result.Friday.length;
                    StatisticsResult.send_date = {
                        'Monday': {
                            count: result.Monday.length,
                            percentage: `${Math.round(result.Monday.length / dateTotal * 100)}%`
                        },
                        'Tuesday': {
                            count: result.Tuesday.length,
                            percentage: `${Math.round(result.Tuesday.length / dateTotal * 100)}%`
                        },
                        'Wednesday': {
                            count: result.Wednesday.length,
                            percentage: `${Math.round(result.Wednesday.length / dateTotal * 100)}%`
                        },
                        'Thursday': {
                            count: result.Thursday.length,
                            percentage: `${Math.round(result.Thursday.length / dateTotal * 100)}%`
                        },
                        'Friday': {
                            count: result.Friday.length,
                            percentage: `${Math.round(result.Friday.length / dateTotal * 100)}%`
                        },
                        total: dateTotal

                    }
                    main_callback(error, 'done');
                })
            },
            send_time_interval: (main_callback) => {
                async.parallel({
                    between_7_To_8: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_time_interval: '7:00-8:00' }, callback)
                    },
                    between_12_To_13: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_time_interval: '12:00-13:00' }, callback)
                    },
                    between_18_To_19: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_time_interval: '18:00-19:00' }, callback)
                    },
                    others: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ send_time_interval: '其他时间' }, callback)
                    },

                }, (error, result) => {
                    if (error) {
                        me.logger.error(error);
                    }
                    var sendTimeIntervalTotal = result.between_7_To_8.length + result.between_12_To_13.length + result.between_18_To_19.length +
                        result.others.length;
                    StatisticsResult.send_time_interval = {
                        'between_7_To_8': {
                            count: result.between_7_To_8.length,
                            percentage: `${Math.round(result.between_7_To_8.length / sendTimeIntervalTotal * 100)}%`
                        },
                        'between_12_To_13': {
                            count: result.between_12_To_13.length,
                            percentage: `${Math.round(result.between_12_To_13.length / sendTimeIntervalTotal * 100)}%`
                        },
                        'between_18_To_19': {
                            count: result.between_18_To_19.length,
                            percentage: `${Math.round(result.between_18_To_19.length / sendTimeIntervalTotal * 100)}%`
                        },
                        'others': {
                            count: result.others.length,
                            percentage: `${Math.round(result.others.length / sendTimeIntervalTotal * 100)}%`
                        },
                        total: sendTimeIntervalTotal

                    }
                    main_callback(error, 'done');
                })
            },
            increased_Fans: (main_callback) => {
                async.parallel({
                    within_500: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ increased_Fans: { $gte: 0, $lt: 500 } }, callback)
                    },
                    between_500_To_1000: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ increased_Fans: { $gte: 500, $lt: 1000 } }, callback)
                    },
                    between_1000_To_1500: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ increased_Fans: { $gte: 1000, $lt: 1500 } }, callback)
                    },
                    greater_than_1500: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ increased_Fans: { $gte: 1500 } }, callback)
                    },

                }, (error, result) => {
                    if (error) {
                        me.logger.error(error);
                    }
                    var increased_FansTotal = result.within_500.length + result.between_500_To_1000.length + result.between_1000_To_1500.length +
                        result.greater_than_1500.length;
                    StatisticsResult.increased_Fans = {
                        'within_500': {
                            count: result.within_500.length,
                            percentage: `${Math.round(result.within_500.length / increased_FansTotal * 100)}%`
                        },
                        'between_500_To_1000': {
                            count: result.between_500_To_1000.length,
                            percentage: `${Math.round(result.between_500_To_1000.length / increased_FansTotal * 100)}%`
                        },
                        'between_1000_To_1500': {
                            count: result.between_1000_To_1500.length,
                            percentage: `${Math.round(result.between_1000_To_1500.length / increased_FansTotal * 100)}%`
                        },
                        'greater_than_1500': {
                            count: result.greater_than_1500.length,
                            percentage: `${Math.round(result.greater_than_1500.length / increased_FansTotal * 100)}%`
                        },
                        total: increased_FansTotal

                    }
                    main_callback(error, 'done');
                })
            },
            total_Fans: (main_callback) => {
                async.parallel({
                    within_10000: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ total_Fans: { $gte: 0, $lt: 10000 } }, callback)
                    },
                    between_10000_To_50000: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ total_Fans: { $gte: 10000, $lt: 50000 } }, callback)
                    },
                    between_50000_To_100000: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ total_Fans: { $gte: 50000, $lt: 100000 } }, callback)
                    },
                    greater_than_100000: (callback) => {
                        me.FHTLiteResearch.findTotalFactor({ total_Fans: { $gte: 100000 } }, callback)
                    },

                }, (error, result) => {
                    if (error) {
                        me.logger.error(error);
                    }
                    var FansTotal = result.within_10000.length + result.between_10000_To_50000.length + result.between_50000_To_100000.length +
                        result.greater_than_100000.length;
                    StatisticsResult.total_Fans = {
                        'within_10000': {
                            count: result.within_10000.length,
                            percentage: `${Math.round(result.within_10000.length / FansTotal * 100)}%`
                        },
                        'between_10000_To_50000': {
                            count: result.between_10000_To_50000.length,
                            percentage: `${Math.round(result.between_10000_To_50000.length / FansTotal * 100)}%`
                        },
                        'between_50000_To_100000': {
                            count: result.between_50000_To_100000.length,
                            percentage: `${Math.round(result.between_50000_To_100000.length / FansTotal * 100)}%`
                        },
                        'greater_than_100000': {
                            count: result.greater_than_100000.length,
                            percentage: `${Math.round(result.greater_than_100000.length / FansTotal * 100)}%`
                        },
                        total: FansTotal

                    }
                    main_callback(error, 'done');
                })
            }
        }, (error, result) => {
            if (error) {
                me.logger.error(error);
            }
            if (result.increased_Fans == 'done' && result.send_date == 'done' && result.send_frequency == 'done'
                && result.send_time_interval == 'done' && result.total_Fans == 'done') {
                //所有数据已经计算好单个算占百分比和整数, 把StatisticsResult返回进行下一步操作
                parentCallback(error, StatisticsResult);
            } else {
                me.logger.error('有部分数据并没有计算成功,请检查');
            }
        })
    }

    /** calculate the final result 
     * @name saveOrUpdateSystemUser
     * @param {Object} StatisticsResult   - 带有之前计算好的每个调查问题的计算结果的对象
     * @param {Number} lossPercent        - 计算出来流量丢失率 NB:不带百分比，最后再附上百分比  
     * @param {Function} parentCallback 
     * 
     * @returns {void}
     */
    calculateUserResult(StatisticsResult, parentCallback) {
        //1.根据loss_rate这个字段算出排名 3.根据排名算出评分
        async.waterfall([
            (callback) => {
                var me = this;
                me.FHTLiteResearch.findAllLostRateByDescOrder((error, result) => {
                    if (error) {
                        me.logger.error(error);
                    }
                    //开始计算排名
                    StatisticsResult.conclusionResult.rank = 0;
                    //拿到当前用户
                    var loss_rate = StatisticsResult.conclusionResult.loss_rate;
                    loss_rate = Number(`${loss_rate.substring(0, loss_rate.length - 1)}`);
                    for (var i = 0; i < result.length; i++) {
                        var currentRate = result[i]._doc.loss_rate;
                        if (loss_rate === currentRate) {
                            StatisticsResult.conclusionResult.rank = i + 1;
                            break;
                        }
                    }
                    console.log(StatisticsResult.conclusionResult.rank);
                    var rank = StatisticsResult.conclusionResult.rank;
                    if (rank >= 0 && rank < 20) {
                        StatisticsResult.conclusionResult.score = Math.round(Math.random() * 9 + 90);
                        console.log(StatisticsResult.conclusionResult.score);
                    } else if (rank >= 20 && rank < 40) {
                        StatisticsResult.conclusionResult.score = Math.round(Math.random() * 9 + 80);
                    } else if (rank >= 20 && rank < 60) {
                        StatisticsResult.conclusionResult.score = Math.round(Math.random() * 9 + 70);
                    } else if (rank >= 60 && rank < 100) {
                        StatisticsResult.conclusionResult.score = Math.round(Math.random() * 9 + 60);
                    } else if (rank >= 100 && rank < 300) {
                        StatisticsResult.conclusionResult.score = Math.round(Math.random() * 9 + 50);
                    } else if (rank >= 300 && rank < 500) {
                        StatisticsResult.conclusionResult.score = Math.round(Math.random() * 9 + 40);
                    } else if (rank >= 500 && rank < 1000) {
                        StatisticsResult.conclusionResult.score = Math.round(Math.random() * 9 + 30);
                    } else if (rank >= 1000 && rank < 2000) {
                        StatisticsResult.conclusionResult.score = Math.round(Math.random() * 9 + 20);
                    }
                    parentCallback(error, StatisticsResult);
                })

            }
        ])
    }


    /**
    * Save or update the user information
    * 
    * @name saveOrUpdateSystemUser
    * @param {String} name - The user name
    * @param {String} email - The user email
    * @param {String} password - The user password
    * @param {Array} refs - The refs for current user
    * @param {String} locale - The default locale for user
    * @param {Object} thirdPartyId - The third party id
    * @param {Function} parentCallback - The callback function
    * 
    * @returns {void}
    */
    saveOrUpdateSystemUser(name, email, password, refs, locale, thirdPartyId, parentCallback) {
        var me = this;
        async.waterfall([
            function (callback) {
                me.User.findUserByEmail(email.toLocaleLowerCase(), callback)
            }, function (result) {
                if (result) {
                    if (result.length > 0) {
                        parentCallback({
                            success: false,
                            data: { //TODO: need to refactor, this is not a good way
                                id: result[0].id,
                                name: name,
                                email: email.toLowerCase(),
                                profile_image: result[0].profile_image,
                                hash_id: result[0].identifier,
                                ref: result[0].ref
                            },
                            error: '该邮箱已经注册，请使用其他邮箱注册！'
                        });
                    } else {
                        var identifier = utils.generateIdentifier();
                        var ref = refs && refs.length > 0 && refs[refs.length - 1] || 'direct';
                        var user = new me.User({
                            name: name,
                            email: email,
                            password: password,
                            hash_id: identifier,
                            locale: locale,
                            third_party_id: thirdPartyId,
                            ref: ref
                        });
                        user.save(function (error, user) {
                            if (error) {
                                me.logger.error('Error happened when signup: ', error);
                                parentCallback({
                                    success: false,
                                    error: '系统繁忙，请稍后再试!'
                                });
                            } else {
                                parentCallback({
                                    success: true,
                                    data: {
                                        id: user.id,
                                        name: name,
                                        email: email,
                                        profile_image: user.profile_image,
                                        hash_id: identifier,
                                        ref: ref,
                                    }
                                });
                            }
                        });
                    }
                } else {
                    parentCallback({
                        success: false,
                        error: '系统繁忙，请稍后再试！'
                    })
                }
            }
        ]);
    }

    /**
     * Verify the password by password
     * 
     * @name verifyPassword
     * @param {String} email - The email address
     * @param {String} password - The password
     * @param {Function} parentCallback - The callback function
     * 
     * @returns {void}
     */
    verifyPassword(email, password, parentCallback) {
        var me = this;
        async.waterfall([
            (callback) => {
                me.User.findUserByEmail(email.toLowerCase(), callback);
            },
            (result, callback) => {
                if (result) {
                    if (result.length === 0) {
                        parentCallback({
                            success: false,
                            code: 400,
                            error: 'login.errors.wrong_email_or_password'
                        });
                    } else {
                        var user = result[0];
                        if (user.password === password) {
                            callback(null, user);
                        } else {
                            parentCallback({
                                success: false,
                                error: 'login.errors.wrong_email_or_password'
                            });
                        }
                    }
                } else {
                    parentCallback({
                        success: false,
                        error: 'global.errors.system_busy'
                    });
                }
            },
            (user, callback) => {
                let data = {
                    success: true,
                    data: {
                        id: user.id,
                        name: user.name,
                        profile_image: user.profile_image,
                        hash_id: user.hash_id,
                        ref: user.ref
                    }
                };

                parentCallback(data);
            }
        ]);
    }

    /**
     * Get lead flows by user id
     * 
     * @param {String} userId 
     * @param {Object} params 
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    getLeadFlowsByUserId(userId, params, parentCallback) {
        var me = this;
        this.LeadFlow.findLeadFlowsByUserId(userId, params, (error, result) => {
            if (!error) {
                var leadflows = result.leadflows;
                result.leadflows = [];
                var functionChain = [];
                leadflows.forEach((leadflow) => {
                    functionChain.push((callback) => {
                        var lf = {
                            id: leadflow.id,
                            name: leadflow.name,
                            created_date: leadflow.created_date.getTime()
                        };

                        if (params.fetch_settings) {
                            lf.settings = leadflow.settings;
                        }
                        if (params.fetch_settings) {
                            result.leadflows.push(lf);
                            callback(null);
                        } else {
                            me.CollectedLead.findLeadsByLeadflowId(leadflow.id, {}, (error, result2) => {
                                lf.impressions = 0; //TODO: need fetch data from tracking system
                                lf.leads = error ? 0 : result2.totalCount;
                                result.leadflows.push(lf);
                                callback(null);
                            });
                        }
                    });
                });
                functionChain.push(() => {
                    parentCallback({
                        success: true,
                        data: result
                    });
                });
                async.waterfall(functionChain);
            } else {
                parentCallback({
                    success: false,
                    error: '系统繁忙，请稍后再试！'
                });
            }
        });
    }

    /**
     * Get leadflow settings by user id
     * 
     * @param {String} userId 
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    getLeadFlowSettingsByUserId(userId, parentCallback) {
        this.getLeadFlowsByUserId(userId, {
            pageSize: 20,
            pageIndex: 1,
            fetch_settings: true
        }, (result) => {
            if (result.success) {
                var leadflows = [];
                result.data.leadflows.forEach((leadflow) => {
                    var settings = leadflow.settings || {};
                    settings.id = leadflow.id;
                    leadflows.push(settings);
                });
                parentCallback(leadflows);
            } else {
                parentCallback([]);
            }
        })
    }

    /**
     * Get collected leads by leadflow id
     * 
     * @param {String} leadflowId 
     * @param {Object} params 
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    getCollectedLeadsByLeadflowId(leadflowId, params, parentCallback) {
        var me = this;
        this.CollectedLead.findLeadsByLeadflowId(leadflowId, params, (error, result) => {
            if (!error) {
                var leads = []
                result.leads.forEach((lead) => {
                    leads.push({
                        id: lead.id,
                        name: lead.name,
                        email: lead.email,
                        phone_number: lead.phone_number,
                        created_date: lead.created_date.getTime()
                    })
                });
                result.leads = leads;
                parentCallback({
                    success: true,
                    data: result
                });
            } else {
                me.logger.error(error);
                parentCallback({
                    success: false,
                    error: '系统繁忙，请稍后再试！'
                });
            }
        });
    }

    getCollectedLeadsByConditions(conditions, params, parentCallback) {
        var me = this;
        this.CollectedLead.findLeadsByConditions(conditions, params, (error, result) => {
            if (!error) {
                var leads = []
                result.leads.forEach((lead) => {
                    leads.push({
                        id: lead.id,
                        name: lead.name,
                        email: lead.email,
                        phone_number: lead.phone_number,
                        created_date: lead.created_date.getTime(),
                        trash: lead.trash
                    })
                });
                result.leads = leads;
                parentCallback({
                    success: true,
                    data: result
                });
            } else {
                me.logger.error(error);
                parentCallback({
                    success: false,
                    error: '系统繁忙，请稍后再试！'
                });
            }
        });
    }

    getContactDataByConditions(conditions, parentCallback) {
        var me = this;
        this.CollectedLead.getCollectedDataByConditions(conditions, (error, result) => {
            if (!error) {
                var leads = []
                result.leads.forEach((lead) => {
                    leads.push({
                        id: lead.id,
                        name: lead.name,
                        email: lead.email,
                        phone_number: lead.phone_number,
                        created_date: lead.created_date.getTime(),
                        trash: lead.trash
                    })
                });
                result.leads = leads;
                parentCallback({
                    success: true,
                    data: result
                });
            } else {
                me.logger.error(error);
                parentCallback({
                    success: false,
                    error: '系统繁忙，请稍后再试！'
                });
            }
        });
    }

    generateDefaultLeadFlowMetadata(userId, parentCallback) {
        var me = this;
        var metadata = defaultLeadflowMetadata;
        var name = `我的线索收集${(new Date()).getTime()}`;
        metadata.name = name;
        var leadflow = new this.LeadFlow({
            user_id: userId,
            name: name,
            settings: metadata
        });
        leadflow.save((error, flow) => {
            if (error) {
                me.logger.error(error);
                parentCallback(null);
            } else {
                parentCallback(flow.id);
            }
        });
    }

    /**
     * Get leadflow metadata by id
     * 
     * @param {String} leadflowId 
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    getLeadFlowMetadataById(leadflowId, parentCallback) {
        var me = this;
        this.LeadFlow.findLeadFlowById(leadflowId, (error, result) => {
            if (error) {
                me.logger.error(error);
                parentCallback({
                    success: false,
                    error: '系统繁忙，请稍后再试！'
                });
            } else {
                parentCallback({
                    success: true,
                    data: result.settings
                });
            }
        });
    }

    getLeadFlowById(leadflowId, parentCallback) {
        var me = this;
        this.LeadFlow.findLeadFlowById(leadflowId, (error, result) => {
            if (error) {
                me.logger.error(error);
                parentCallback({
                    success: false,
                    error: '系统繁忙，请稍后再试！'
                });
            } else {
                parentCallback({
                    success: true,
                    data: {
                        id: result.id,
                        name: result.name,
                        settings: result.settings
                    }
                });
            }
        });
    }

    /**
     * Update leadflow metadata by id
     * 
     * @param {String} leadflowId 
     * @param {Object} metadata 
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    updateLeadFlowMetadataById(leadflowId, metadata, parentCallback) {
        var me = this;
        this.LeadFlow.findLeadFlowById(leadflowId, (error, leadflow) => {
            if (!error) {
                if (!leadflow) {
                    parentCallback({
                        success: false,
                        error: '线索收集框不存在！'
                    });
                } else {
                    leadflow.set({
                        settings: metadata,
                        name: metadata.name,
                        last_updated_date: new Date()
                    });
                    leadflow.save((error, flow) => {
                        if (error) {
                            parentCallback({
                                success: false,
                                error: '系统繁忙，请稍后再试！'
                            })
                        } else {
                            parentCallback({
                                success: true,
                                data: "OK"
                            });
                        }
                    });
                }
            } else {
                me.logger.error(error);
                parentCallback({
                    success: false,
                    error: '系统繁忙，请稍后再试！'
                })
            }
        });
    }

    /**
     * Remove lead flow by id
     * 
     * @param {String} leadflowId 
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    removeLeadFlowById(leadflowId, parentCallback) {
        var me = this;

        async.waterfall([
            (callback) => {
                me.CollectedLead.removeLeadsByLeadflowId(leadflowId, (error, result) => {
                    if (error) {
                        me.logger.error(error);
                        parentCallback({
                            success: false,
                            error: '系统繁忙，请稍后再试！'
                        })
                    } else {
                        callback(null);
                    }
                });
            },
            (callback) => {
                me.LeadFlow.removeById(leadflowId, (error, result) => {
                    if (error) {
                        me.logger.error(error);
                        parentCallback({
                            success: false,
                            error: '系统繁忙，请稍后再试！'
                        })
                    } else {
                        parentCallback({
                            success: true,
                            data: 'OK'
                        });
                    }
                });
            }
        ]);
    }

    /**
     * Remove contact by id
     * 
     * @param {String} contactId 
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    removeContactById(contactId, parentCallback) {
        var me = this;

        async.waterfall([
            (callback) => {
                me.CollectedLead.removeContactById(contactId, (error, result) => {
                    if (error) {
                        me.logger.error(error);
                        parentCallback({
                            success: false,
                            error: '系统繁忙，请稍后再试！'
                        })
                    } else {
                        callback(null);
                    }
                });
            },
            (callback) => {
                me.CollectedLead.removeById(contactId, (error, result) => {
                    if (error) {
                        me.logger.error(error);
                        parentCallback({
                            success: false,
                            error: '系统繁忙，请稍后再试！'
                        })
                    } else {
                        parentCallback({
                            success: true,
                            data: 'OK'
                        });
                    }
                });
            }
        ]);
    }

    /**
     * Update the collectedLead's information
     * 
     * @name updateContact
     * @param {Object} contactInfo - The contactInfo need to update
     * @param {Function} parentCallback - The callback function
     * 
     * @returns {void}
     */
    //TODO: need to rewrite the fucking shit code
    updateContact(contactInfo, parentCallback) {
        var me = this;
        !contactInfo.email && (delete contactInfo.email);
        !contactInfo.name && (delete contactInfo.name);
        !contactInfo.phone_number && (delete contactInfo.phone_number);
        !contactInfo.trash && (delete contactInfo.trash);
        async.waterfall([
            (callback) => { //Check id is right or not
                me.CollectedLead.findCollectedLeadById(contactInfo.id, (error, collectedLead) => {
                    if (error) {
                        parentCallback({
                            success: false,
                            error: '系统繁忙，请稍后再试！'
                        })
                    } else {
                        if (contactInfo.email) {
                            contactInfo.email = contactInfo.email.toLowerCase();
                        }
                        delete contactInfo.id;
                        collectedLead.set(contactInfo);
                        collectedLead.save(function (error, collectedLead) {
                            parentCallback({
                                success: true,
                                data: "OK"
                            });
                        })
                    }
                });
            }
        ]);
    }

    /**
     * Update the system user's information
     * 
     * @name updateUserProfile
     * @param {Object} data - The data need to update
     * @param {Function} parentCallback - The callback function
     * 
     * @returns {void}
     */
    //TODO: need to rewrite the fucking shit code
    updateUserProfile(data, parentCallback) {
        var me = this;
        !data.email && (delete data.email);
        !data.profile_image && (delete data.profile_image);
        !data.name && (delete data.name);
        !data.new_password && (delete data.new_password);
        !data.old_password && (delete data.old_password);
        async.waterfall([
            (callback) => { //Check if password need to change
                if (data.new_password && data.old_password) {
                    me.User.findUserById(data.id, (error, user) => {
                        if (error) {
                            parentCallback({
                                success: false,
                                error: '系统繁忙，请稍后再试！'
                            })
                        }
                        if (user.password === data.old_password) {
                            data.password = data.new_password;
                            callback(null);
                        } else {
                            parentCallback({
                                success: false,
                                error: '原密码输入错误'
                            });
                        }
                    });
                } else {
                    callback(null);
                }
            }, () => {
                me.User.findUserById(data.id, function (error, user) {
                    if (error) {
                        //TODO: Added log here
                        parentCallback({
                            success: false,
                        });
                    } else {
                        if (data.email) {
                            data.email = data.email.toLowerCase();
                        }
                        delete data.id;
                        user.set(data);
                        user.save(function (error, user) {
                            parentCallback({
                                success: true,
                                data: "OK"
                            });
                        })
                    }
                });
            }
        ]);
    }

    /**
     * Get the system user information by id
     * 
     * @name getUserProfile
     * @param {String} userId - The user id
     * @param {Function} parentCallback - The callback function
     * 
     * @returns {void}
     */
    getUserProfile(userId, parentCallback) {
        var me = this;
        me.User.findUserById(userId, function (error, user) {
            parentCallback(user);
        })
    }

    /**
     * Get system setting by setting name
     * 
     * @param {String} userId 
     * @param {String} settingName 
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    getSystemSettingByName(userId, settingName, parentCallback) {
        var me = this;
        var defaultSetting = defaultSettings[settingName];
        this.SystemSetting.findSettingByName(userId, settingName, (error, result) => {
            if (error) {
                me.logger.error(error);
                parentCallback({
                    success: true,
                    data: {
                        is_default: true,
                        value: defaultSetting
                    }
                });
            } else {
                if (result && result.length > 0) {
                    parentCallback({
                        success: true,
                        data: {
                            is_default: false,
                            value: result[0].setting_value
                        }
                    });
                } else {
                    parentCallback({
                        success: true,
                        data: {
                            is_default: true,
                            value: defaultSetting
                        }
                    });
                }
            }
        });
    }

    /**
     * Get all system settings
     * 
     * @param {String} userId 
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    getSystemSettings(userId, parentCallback) {
        var me = this;
        this.SystemSetting.findSettingsByUserId(userId, (error, result) => {
            if (error) {
                me.logger.error(error);
                parentCallback(defaultSettings);
            } else {
                var settings = utils.cloneObject(defaultSettings);
                result.forEach((setting) => {
                    settings[setting.setting_name] = setting.setting_value;
                });

                parentCallback(settings);
            }
        });
    }

    /**
     * Update system setting by name
     * 
     * @param {String} userId 
     * @param {String} settingName 
     * @param {any} settingValue 
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    updateSystemSettingByName(userId, settingName, settingValue, parentCallback) {
        var me = this;
        this.getSystemSettingByName(userId, settingName, (result) => {
            if (result.success && result.data.is_default) {
                var setting = new me.SystemSetting({
                    user_id: userId,
                    setting_name: settingName,
                    setting_value: settingValue
                });
                setting.save((error, doc) => {
                    if (error) {
                        me.logger.error(error);
                        parentCallback({
                            success: false,
                            error: '系统繁忙，请稍后再试！'
                        })
                    } else {
                        parentCallback({
                            success: true,
                            data: doc.id
                        });
                    }
                });
            } else {
                me.SystemSetting.findSettingByName(userId, settingName, (error, result) => {
                    if (error) {
                        me.logger.error(error);
                        parentCallback({
                            success: false,
                            error: '系统繁忙，请稍后再试！'
                        });
                    } else {
                        result[0].set({
                            setting_value: settingValue,
                            last_updated_date: new Date()
                        });
                        result[0].save((error, doc) => {
                            if (error) {
                                me.logger.error(error);
                                parentCallback({
                                    success: false,
                                    error: '系统繁忙，请稍后再试！'
                                })
                            } else {
                                parentCallback({
                                    success: true,
                                    data: doc.id
                                });
                            }
                        });
                    }
                });
            }
        })
    }

    /**
     * Check if user exists with email
     * 
     * @param {String} email 
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    checkUserByEmail(email, parentCallback) {
        var me = this;
        this.User.findUserByEmail(email, (error, result) => {
            if (error) {
                me.logger.error(error);
                parentCallback({
                    success: false,
                    error: '系统繁忙，请稍后再试！'
                });
            } else {
                if (result && result.length === 0) {
                    parentCallback({
                        success: false,
                        error: '没有发现使用该邮箱的用户！'
                    });
                } else {
                    //TODO: send email to user
                    parentCallback({
                        success: true,
                        data: "OK"
                    });
                }
            }
        });
    }

    generateResetPasswordMetadata(email, parentCallback) {

    }

    /**
     * Save collected lead
     * 
     * @param {String} leadflowId - The lead flow id
     * @param {Object} params - The lead data
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    saveCollectedLead(leadflowId, data, parentCallback) {

        var me = this;
        var lead = {};
        lead.leadflow_id = leadflowId;
        lead.name = data.name || null;
        lead.email = data.email || null;
        lead.phone_number = data.phone_number || null;
        lead.user_agent = data.user_agent || null;
        lead.remote_ip = data.remote_ip || null;
        lead.session_id = data.session_id;
        lead.http_referer = data.http_referer;

        var leadDoc = new this.CollectedLead(lead);

        leadDoc.save((error, doc) => {
            var data = null;
            if (error) {
                me.logger.error(error, { lead: lead });
            } else {
                data = doc.id;
            }

            parentCallback({
                success: true,
                data: data
            });
        });
    }

    /**
     * get dashboard charts data
     * 
     * @param {String} userId 
     * @param {Function} parentCallback 
     * 
     * @memberOf LeadBarService
     */
    getDashboardDataByUserId(userId, parentCallback) {
        var me = this;
        var chartData = [];
        this.LeadFlow.getLeadFlowsByUserId(userId, (error, result) => {
            if (!error) {
                var leadflows = result.leadflows;
                result.leadflows = [];
                var functionChain = [];
                leadflows.forEach((leadflow) => {
                    functionChain.push((callback) => {
                        me.CollectedLead.getDataByLeadflowId(leadflow.id, (error, result2) => {
                            if (error) {
                                return parentCallback({
                                    success: false,
                                    error: error
                                });
                            } else {
                                chartData = chartData.concat(result2);
                                callback(null);
                            }
                        });
                    });
                });
                functionChain.push(() => {
                    var array = [], start_date = new Date().getTime() - 2592000000, end_date = new Date().getTime() + 86400000;
                    var distance = 86400000;
                    for (var i = 0; i < 30; i++) {
                        array.push({ count: 0, date: moment(start_date + i * distance).format('MM/DD') });
                    }
                    chartData.forEach((record, index) => {
                        for (var i = 0; i < 30; i++) {
                            if (start_date + i * distance <= record.created_date && record.created_date <= start_date + (i + 1) * distance) {
                                array[i].count += 1;
                                array[i].date = moment(start_date + i * distance).format('MM/DD');
                            } else {
                                array[i].count = 0;
                                array[i].date = moment(start_date + i * distance).format('MM/DD');

                            }
                        }
                    });
                    parentCallback({
                        success: true,
                        data: array
                    });
                });
                async.waterfall(functionChain);
            } else {
                parentCallback({
                    success: false,
                    error: '系统繁忙，请稍后再试！'
                });
            }
        });


    }




}

exports.LeadBarService = LeadBarService;